import type { NavigationGuardNext, RouteLocationNormalized, Router } from 'vue-router';
import type { RouteKey, RoutePath } from '@elegant-router/types';
import { useRouteStore } from '@/store/modules/route';
import { localStg } from '@/utils/storage';
import { createUserApi, getToken } from '@/service/api';

export function createPermissionGuard(router: Router) {
  router.beforeEach(async (to, from, next) => {
    const pass = await createAuthRouteGuard(to, from, next);
    if (!pass) return;

    // 1. route with href
    if (to.meta.href) {
      window.open(to.meta.href, '_blank');
      next({ path: from.fullPath, replace: true, query: from.query, hash: to.hash });
    }

    if (to.name === '403') {
      next();
      return;
    }

    // URL 中的 token 拦截
    // const noPermissionRoute: RouteKey = '403';
    const hasURLToken = Boolean(to.query.token);
    const hasToken = Boolean(localStg.get('humanToken'));
    console.log(hasURLToken, hasToken, to.query.token, localStg.get('humanToken'));
    if (hasURLToken) {
      localStg.set('source-token', to.query.token as string);
      // eslint-disable-next-line no-promise-executor-return
      await new Promise(resolve => setTimeout(resolve, 10));
      const result = await fetchTokenFn(to);
      console.log(result);
      if (result) {
        // 去掉token参数
        const newQuery = { ...to.query };
        delete newQuery.token;
        next({
          name: to.name as RouteKey,
          query: newQuery
        });
        return;
      }
      if (!hasToken) {
        const url = import.meta.env.VITE_SERVICE_LOGOUT_URL;
        // 获取当前页面的URL组件
        const protocol = window.location.protocol; // 获取协议，例如 'http:'
        const hostname = window.location.hostname; // 获取主机名，例如 'example.com'
        const port = window.location.port; // 获取端口号，如果有的话

        // 构建根路径
        let rootUrl = `${protocol}//${hostname}`;
        if (port) {
          rootUrl += `:${port}`;
        }
        rootUrl += '/product-list';
        window.open(`${url}?humanRedirect=${encodeURIComponent(rootUrl)}`, '_self');
        return;
      }
    }
    if (hasToken) {
      next();
      return;
    }

    // 拼接上token 参数
    next({
      name: to.name as RouteKey,
      query: {
        ...to.query
      }
    });
  });
}

// 初始化进入获取系统token
async function fetchTokenFn(to: RouteLocationNormalized) {
  try {
    const { data } = await getToken(to.query.token as any);
    const mobile = (to.query.mobile as string) || '';
    console.log(data, 'isFetchTokenFn dada');
    localStorage.setItem('video-mobile', mobile);
    if (data.token) {
      localStg.set('humanToken', data.token); // 写token
      localStg.set('userId', data.userid || data.userId || data.account); // 不知道字段，userid
      try {
        await createUserApi({ mobile });
      } catch (error) {
        console.log(error);
      }
      return Promise.resolve(true);
    }
    localStg.remove('humanToken');
    return Promise.resolve(false);
  } catch (error) {
    localStg.remove('humanToken');
    return Promise.resolve(false);
  }
}

async function createAuthRouteGuard(
  to: RouteLocationNormalized,
  _from: RouteLocationNormalized,
  next: NavigationGuardNext
) {
  const notFoundRoute: RouteKey = 'not-found';
  const isNotFoundRoute = to.name === notFoundRoute;

  // 1. If the route is the constant route but is not the "not-found" route, then it is allowed to access.
  if (to.meta.constant && !isNotFoundRoute) {
    return true;
  }

  // 2. If the auth route is initialized but is not the "not-found" route, then it is allowed to access.
  const routeStore = useRouteStore();
  if (routeStore.isInitAuthRoute && !isNotFoundRoute) {
    return true;
  }

  // 3. If the route is initialized, check whether the route exists.
  if (routeStore.isInitAuthRoute && isNotFoundRoute) {
    const exist = await routeStore.getIsAuthRouteExist(to.path as RoutePath);

    if (exist) {
      const noPermissionRoute: RouteKey = '403';

      next({ name: noPermissionRoute });

      return false;
    }

    return true;
  }

  // 4. If the user is not logged in, then redirect to the login page.
  const isLogin = Boolean(localStg.get('humanToken')) || Boolean(to.query.token);
  if (!isLogin) {
    const noPermissionRoute: RouteKey = '403';
    next({ name: noPermissionRoute });

    return false;
  }

  // 5. init auth route
  await routeStore.initAuthRoute();

  // 6. the route is caught by the "not-found" route because the auto route is not initialized. after the auto route is initialized, redirect to the original route.
  if (isNotFoundRoute) {
    const rootRoute: RouteKey = 'root';
    const path = to.redirectedFrom?.name === rootRoute ? '/' : to.fullPath;

    next({ path, replace: true, query: to.query, hash: to.hash });

    return false;
  }

  return true;
}
